(function(ns, win, doc, cfgs){

ns.Balls = new Class({
    Extends: ns.Base,
    Binds: ['onClick'],
    options: {
        title: '选择号码',
        balls: null,
        min: 0,
        max: 9,
        mid: 5,
        lower:0,
        upper:100,
        isBile: false,
		className: '',
        bileClass: 'bile',
        container: 'div.body',
        ballClass: '.ball',
        ballSelectedClass: 'on',
        actionSelectedClass: 'selected',
        tpl: 'tpl_balls',
		pad: true
    },
    build: function(ops, self) {
        var container = self.container = new Element(ops.container),
            balls,
            keys,
			pad = ops.pad,
			className = ops.className,
            min = ops.min.min(ops.max),
            max = ops.max.max(ops.min);
        ops.min = min;
        ops.max = max;
        self.tpl = Template(ops.tpl);
		if ( className ) container.addClass(className);
        if (ops.balls && typeOf(ops.balls) == 'array') {
            balls = ops.balls;
        } else {
            balls = [];
            for (; min <= max;){
				balls.push(min ? (pad ? min.pad() : min) : '0');
				min ++;
            }
        }
        self.balls = balls;
        self.actions = {
            full: balls.join(','), 
            big: balls.filter(function(ball, i){return i >= ops.mid;}).join(','),
            small: balls.filter(function(ball, i){return i < ops.mid;}).join(','),
            odd: balls.filter(function(ball){return ball %2;}).join(','),
            even: balls.filter(function(ball){return ball % 2 == 0;}).join(',')
        };
        keys = Object.keys(self.actions).each(function (key) {
            self.actions[self.actions[key]] = key;
        });
        container.set('html', self.tpl({title: ops.title, balls: balls}));
        if (ops.isBile) {
            container.addClass(ops.bileClass);
        }
    },
    observe: function(self, action, actions) {
        self.container[action]('click', self.onClick);
    },
    updateHistory: function (data) {
        if (!data) {
            return;
        }
        var self = this,
            ops = self.options,
            min = ops.min,
            red = 'red',
            balls = self.container.getElements(ops.ballClass + ' i').set('text', 0).removeClass(red);
        if (typeOf(data) == 'object') {
            Object.each(data, function (v, k) {
				if ( balls[k - min] ) {
					balls[k - min].set('text', v)[v < 5 ? 'removeClass': 'addClass'](red);
				}
            });
        }
    },
    onClick: function (e) {
        var self = this,
            ops = self.options,
            cls = ops.ballClass,
            el = doc.id(e.target),
            ball = el.hasClass(cls) ? el : el.getParent(cls),
            ballSelectedClass = ops.ballSelectedClass,
            actionSelectedClass = ops.actionSelectedClass,
            orderBalls = self.orderBalls = self.orderBalls || [],
            balls,
            i,
            act;
        if (ball) {
            ball.toggleClass(ballSelectedClass);
            if (self.lastAction) {
                self.lastAction.removeClass(actionSelectedClass);
            }
            balls = self.container.getElements('.' + ballSelectedClass).get('data-i');
            i = ball.get('data-i');
            if (ball.hasClass(ballSelectedClass)) {
                orderBalls.push(i);
                if (!self.check(orderBalls, self, ops)) {
                    return;
                }
            } else {
                orderBalls = orderBalls.erase(i);
            }
            balls = balls.join(',');
            if (self.actions[balls]) {
                act = self.container.getElement('span[data-act=' + self.actions[balls] + ']');
                if (act) {
                    act.addClass(actionSelectedClass);
                    self.lastAction = act;
                }
            }
            self.fireEvent('change', [self, true]);
        } else {
            act = el.get('data-act');
            if (act) {
                self.doAction(act, self, ops, cls, el);
            }
        }
    },
    check: function (orderBalls, self, ops) {
        self = self || this;
        ops = ops || self.options;
        balls = self.container.getElements(ops.ballClass);
        orderBalls = self.orderBalls || [];

        if (orderBalls.length > ops.upper || !arguments.length && orderBalls.length < ops.lower) {
            orderBalls.length && arguments.length && balls[orderBalls.shift() - ops.min].removeClass(ops.ballSelectedClass);
            return !!arguments.length;
        }
        return true;
    },
    doAction: function (act, self, ops, cls, el) {
        var container = self.container,
            on = ops.ballSelectedClass,
            selected = ops.actionSelectedClass,
            balls = container.getElements(cls),
            lastAction = self.lastAction;
        if (lastAction) {
            if (lastAction == el) {
                return;
            }
            lastAction.removeClass(selected);
        }
        switch (act){
        case 'full':
            balls.addClass(on);
            break;
        case 'clear':
            self.orderBalls = [];
            balls.removeClass(on);
            break;
        case 'odd':
            self.balls.each(function (ball, i) {
                balls[i][ ball % 2 ? 'addClass' : 'removeClass'](on);
            });
            break;
        case 'even':
            self.balls.each(function (ball, i) {
                balls[i][ ball % 2 == 0 ? 'addClass' : 'removeClass'](on);
            });
            break;
        case 'big':
            self.balls.each(function (ball, i) {
                balls[i][ i >= ops.mid ? 'addClass' : 'removeClass'](on);
            });
            break;
        case 'small':
            self.balls.each(function (ball, i) {
                balls[i][ i < ops.mid ? 'addClass' : 'removeClass'](on);
            });
            break;
        default:
            return;        
        }
        if (act != 'clear') {
            self.lastAction = el.addClass(selected);
            self.orderBalls = container.getElements(on).get('data-i');
        }
        self.fireEvent('change', [self, false]);
    },
    clear: function () {
        var self = this,
            ops = self.options,
            ballSelectedClass = ops.ballSelectedClass;
        self.container.getElements('.' + ballSelectedClass).removeClass(ballSelectedClass);
        self.orderBalls = [];
        if (self.lastAction) {
            self.lastAction.removeClass(ops.actionSelectedClass);
            self.lastAction = null;
        }
    },
    sort: function (a, b) {
		return (a|0) - (b|0);
    },
    random: function (n) {
        var self = this;
        return self.balls.random(n).sort(self.sort);
    },
    get: function (n) {
        var self = this,
            ops = self.options,
            ballSelectedClass = ops.ballSelectedClass;
        return n ? self.random(n) : self.container.getElements('.' + ballSelectedClass).get('data-i');
    },
    set: function (nums) {
		if (typeof nums == undefined) return;
        var self = this,
			args = typeOf(nums) == 'array' ? nums : nums.split(',');
        self.clear();
        args.unshift(true);
        self.select.apply(self, args);
        args.shift();
        self.orderBalls = args;
    },
    select: function (selected) {
        var self = this,
            ops = self.options,
            balls = self.container.getElements(ops.ballClass),
            action = selected ? 'addClass' : 'removeClass',
            on = ops.ballSelectedClass,
            orderBalls = self.orderBalls;
        Array.slice(arguments, 1).flatten().each(function (n) {
			if ( balls[n - ops.min] ) {
				balls[n - ops.min][action](on);
				if (orderBalls) {
					orderBalls.erase(n);
				}
			}
        });
        if (orderBalls) {
            balls = orderBalls.join(',');
            if (self.actions[balls]) {
                act = self.container.getElement('span[data-act=' + self.actions[balls] + ']');
                if (act) {
                    act.addClass(ops.actionSelectedClass);
                    self.lastAction = act;
                }
            }            
        }
		//self.fireEvent('change', [self, true]);
    },
	addControl: function (ctrl) {
		ctrl.bindTo(this);
	}
});

ns.BileBalls = new Class({
    Extends: ns.Balls,
    options: {
        isBile: true,
        lower:1,
        upper:1
    },
    updateHistory: function (data) {
        
    },
    /*check: function (orderBalls, self, ops) {
        return orderBalls.length > ops.lower;
    },*/
    fix: function (cur, force, ball) {
        var self = this,
            orderBalls = self.orderBalls;
        if (orderBalls && orderBalls.length) {
            if (cur === self || !force) {
                ball.select(false, orderBalls);
            } else {
                self.select(false, orderBalls.filter(function(num){
                    return ball.orderBalls.contains(num);
                }));
            }            
        }
    }
});

ns.ManulBalls = new Class({
    Extends: ns.Base,
    Binds: ['onBlur', 'onFocus', 'onKeyup', 'onChange'],
    options: {
        placeholder: '',
        pad: 2,
        min: 1,
        max: 11,
        length: 3,
        textarea: 'textarea',
        container: 'div.body'
    },
    build: function(ops, self) {
        var container = self.container = new Element(ops.container),
            value = ops.placeholder,
            min = ops.min.min(ops.max),
            max = ops.max.max(ops.min),
            balls;
        ops.min = min;
        ops.max = max;

		if ( ops.reg ) self.reg = ops.reg;

        if (ops.balls && typeOf(ops.balls) == 'array') {
            balls = ops.balls;
        } else {
            balls = [];
            for (; min <= max;){
                balls.push(min++);
            }
        }

        self.balls = balls;
        self.textarea = container.getElement(ops.textarea).set('value', value).set('defaultValue', value);
    },
    observe: function(self, action, actions) {
        self.textarea[actions]({blur: self.onBlur, focus: self.onFocus, keydown: self.onKeyup, change: self.onChange});
    },
    onBlur: function (e) {
        var self = this,
            textarea = self.textarea;
        if (textarea.value.trim() == '') {
            textarea.value = textarea.defaultValue;
        }
    },
    onFocus: function (e) {
        var self = this,
            textarea = self.textarea;
        if (textarea.value == textarea.defaultValue) {
            textarea.value = '';
        }
    },
    onKeyup: function (e) {
        var self = this,
            code = e.code,
            key = e.key;
        if (code == 32 || code == 13 || code == 8) {
            return true;
        }
        if (/[^\d\s,]/.test(key)) {
            e.preventDefault();
        }
    },
    onChange: function (e) {
        this.fireEvent('change', self);
    },
    updateHistory: function () {
        
    },
	getReg: function () {
		var self = this,
			ops = self.options,
			balls,
			reg;
		if ( !self.reg ) {
			balls = self.balls.join('|');
			reg = ['^(((', ') +){' + (ops.length - 1) + '}((', ') ?))$'].join(balls);
			self.reg = new RegExp(reg, 'gm');
		}
		return self.reg;
	},
    check: function () {
        var self = this,
            textarea = self.textarea,
			value = textarea.value.trim();
		value = value.replace(/[^\d\s\r\n,]+/g, '').replace(/(\s|^)0/g, '$1').match(self.getReg());
		return value ? value.invoke('split', /\s+/) : value;
    },
    clear: function () {
        var self = this,
			textarea = self.textarea;
		textarea.value = textarea.defaultValue;
		try {
			textarea.blur();
		} catch (e){
		}
    },
    random: function (n) {
        return this.balls.random(n);
    },
    get: function (n) {
        var self = this,
            textarea = self.textarea,
			matches;
        if (n > 0) {
            return self.random(n);
        }
        matches = self.check()
        if ( matches ) {
            return matches;
        }
		return '';
    }
});

ns.RandomControl = new Class({
	Extends: ns.Base,
	Binds: ['change'],
	options: {
		container: '',
		name: '',
		where: 'top',
		tpl: 'tpl_rnd_ctrl',
		min: 5,
		max: 9
	},
	build: function (ops, self) {
		var container = self.container = ops.container ? doc.getElement(ops.container) : new Element('div.rnd-ctrl'),
			tpl = Template(ops.tpl);
		container.set('html', tpl({min: ops.min, max: ops.max}));
		self.select = container.getFirst();
		self.button = container.getLast();
		if (ops.name ) new Element('em').set('text', ops.name).inject(container, 'top');
	},
	observe: function (self, action, actions) {
		self.button[action]('click', self.change);
	},
	bindTo: function (balls) {
		var self = this,
			ops = self.options;
		self.balls = balls;
		self.inject(balls, ops.where);
	},
	change: function (e) {
		var self = this,
			balls = self.balls,
			nums;
		balls.clear();
		nums = balls.random(self.select.value | 0);
		balls.set(nums);
		balls.fireEvent('change', [balls, true]);
	}
});


ns.Play = new Class({
    Extends: ns.Base,
    Binds: ['change'],
    options: {
        name: '',
        tips: '',
        type: 1,
        bytes: 5,
        cost: 2,
        sum: 0,
		statusTpl: 'tpl_status',
		allRequired: true
    },
    addClass: function (className) {
		this.element.addClass(className);     
    },
    observe: function(self, action, actions) {
        self.balls.invoke(action, 'change', self.change);
    },
    change: function () {
        var self = this;
        self.fireEvent('change', [self.info, self.options.statusTpl]);
    },
    show: function (el) {
        var self = this;
        el.set('html', '<span class="step1"></span>' + self.options.tips);
        self.element.show();
    },
    hide: function () {
        var self = this;
        self.element.hide();
        self.clear();
    },
    clear: function () {
        var self = this;
        self.balls.invoke('clear');
    },
    validate: function () {
        var self = this,
			allRequired = self.options.allRequired,
            balls = self.balls.invoke('get').invoke('count');
		return eval(balls.join('+')) >= this.options.sum && ( !allRequired || eval(balls.join('*')) > 0 );
    },
    random: function (n) {
        
    },
	getTpl: function () {
		return this.options.statusTpl;
	},
    get: function () {
        
    },
    set: function (nums, split) {
        nums = nums.split('|');
        var self = this;
		if ( split ) {
			self.balls.each(function (ball, i) {
				if (nums[i].length) ball.set(nums[i]);
			});
		} else {
			self.balls.each( function ( ball ) {
				ball.set( nums[0] );
			});
		}
    },
	updateStatus: function (el, info) {
		
	},
    updateHistory: function (json) {
        var self = this,
            type = self.options.type,
            data = json[type] || json.other || [],
            isOther = !json[type] && json.other && json.other.length;
        self.balls.map(function(ball, i){ball.updateHistory(isOther ? data[i] || data[0] : data[i])});
    }
});

ns.CombPlay = new Class({
	Extends: ns.Play,
	
	options: {
		statusTpl: 'tpl_status_bile'
	},

    compute: function (balls) {
        var self = this,
            ops = self.options,
            b0Len = balls[0].length,
            b1Len = balls[1].length,
            info = {nums: b0Len + b1Len, count: b0Len > 0 && b1Len >= ops.sum - b0Len ? b1Len.combination(ops.sum - b0Len - 1) : 0};
        info.balls = '胆：' + balls.invoke('join', ',').join(' 拖：');
		info.counts = balls.invoke('count');
        return info;
    },

	change: function (ball, force) {
        var self = this,
            balls = self.balls;
        balls[0].fix(ball, force, balls[1]);
        self.info = self.compute(balls.invoke('get'));
        self.parent(ball, force);
    },

	set: function (nums, split) {
		nums = nums.replace('胆：', '').replace('拖：', '|');
		this.parent(nums, split);
    }
});

ns.ManulPlay = new Class({
    Extends: ns.Base,
    Binds: ['change'],
    options: {
        name: '',
        tips: '',
        type: 1,
        bytes: 5,
        cost: 2,
        sum: 0,
		statusTpl: 'tpl_status'
    },
    build: function (ops, self) {
        self.element = new Element('div').set('html', '<textarea style="width:100%;" rows="5"></textarea>');
        self.balls = new ns.ManulBalls(Object.merge(cfgs.manul || {}, {container: self.element, length: ops.length}));
    },
    observe: function(self, action, actions) {
        self.balls[action]('change', self.change);
    },
	addClass: function (className) {
		this.element.addClass(className);
	},
	getTpl: function () {
		return this.options.statusTpl;
	},
    change: function () {
        var self = this,
            balls = self.balls.check(),
            info;
        info = self.info = {balls: '', nums: 0, count: 0}
        if (balls) {
            info.count = balls.length;
            info.nums = eval(balls.invoke('count').join('+'));
        }
        self.fireEvent('change', self.info);
    },
    show: function (el) {
        var self = this;
        el.set('html', '<span></span>玩法提示：' + self.options.tips);
        self.element.show();
    },
    hide: function () {
        var self = this;
        self.element.hide();
        self.clear();
    },
    clear: function () {
        var self = this;
        self.balls.clear();
    },
    validate: function () {
        var self = this,
            balls = self.balls.check();
        return !!balls;
    },
    random: function (n) {
        
    },
    get: function () {
        
    },
    updateHistory: function (json) {
    }
});

(function(){
var dic = {};
ns.addPlay = function (id, obj, key) {
   key = key || cfgs.key || 'unkown';
    if (typeOf(obj) == 'object') {
       var extend = obj.extend,
           cat = dic[key];
       delete obj.extend;
       if (!cat) {
           cat = dic[key] = {};
       }
       /*extend = cat[extend];
       if (extend && typeOf(extend) == 'object') {
           extend = new Class(extend);
       }
       obj.Extends = extend || ns.Play;*/
       cat[id] = new Class(obj);
       return cat[id];
    }
};
ns.getPlay = function (id, key, cat) {
   key = key || cfgs.key || 'unkown';
   cat = dic[key];
   if (!cat) {
       cat = dic[key] = {};
   }
   if (typeOf(cat[id]) == 'object') {
       cat[id] = new Class(cat[id]);
   }
   if (typeOf(cat[id]) == 'class') {
       return cat[id];
   } else {
       throw new Error('Play Type ' + id + ' in ' + key + ' not found.');
   }
};
})();

var History = new Class({
	Implements: [Events, Options],
    Binds: ['get', 'got'],
    options: {
        url: '',
        periodical: 1000000
    },
	initialize: function(options){
        var self = this,
            ops = self.setOptions(options).options;
        self.xhr = new Request.JSON({secure: false, url: ops.url, onSuccess: self.got, onFailure: function(){clearInterval(self.timer)}});
        self.get(ops.periodical);
    },
    get: function (periodical) {
        var self = this;
        self.xhr.post();
        self.timer = self.xhr.post.periodical(periodical, self.xhr);
    },
    got: function (json) {
        var self = this;
        self.data = json;
        self.fireEvent('got', json, 20);
    }
});

ns.EditPlay = new Class({
    Extends: ns.Base,
    Binds: ['update', 'clear', 'save'],
    options: {
		split: true,
        disabledClass: 'disabled'
    },
    build: function (ops, self) {
        var dialog = self.dialog = new ns.ModelDialog({title: '修改投注', content: '<div class="_tips"></div><div class="step1-coosenum clearfix"></div><div class="cart">' + ops.infoContent + '</div>', width: 695, height: 190, doOk: self.save});
        dialog.contenter.addClass('ball-selector');
        self.tips = dialog.getElement('._tips');
        self.box = dialog.getElement('.step1-coosenum');
		self.info = dialog.getElement(ops.info);
    },
    observe: function (self, action, actions) {
        self.info[action]('click:relay(input)', self.clear);
    },
	fill: function (play, el) {
		var self = this,
            nums = el.get('data-nums'),
		dialog = self.dialog;
		if ( self.play ) self.play.hide();
		self.play = play.addEvent('change', self.update);
        self.current = el;
        play.set(nums, self.options.split);
		play.inject(self.box).show(self.tips);
		play.change();

		self.dialog.show();
	},
    update: function (info, tpl) {
        var self = this,
            ops = self.options;
		info = info || {nums:0, count:0, counts: [0, 0, 0, 0, 0, 0]};
		self.info.set('html', Template(tpl || self.play.getTpl(), info));
		self.dialog.button.ok[info.count ? 'removeClass' : 'addClass'](ops.disabledClass);
    },
    clear: function (e) {
        e && e.preventDefault();
        var self = this;
        self.play.clear();
        self.info.getElements('strong,.blue').set('text', 0);
		self.dialog.button.ok.addClass(self.options.disabledClass);
    },
    save: function () {
        var self = this,
            valid = !self.dialog.button.ok.hasClass(self.options.disabledClass) && self.play.validate();
        if (valid) {
            self.fireEvent('save', [self.play, self.current, self]);
        }
        return valid;
    }
});

ns.StepOne = new Class({
    Extends: ns.Base,
    Binds: ['render', 'update', 'clear', 'updateHistory', 'modify'],
    options: {
        container: '.step-wrap .step',
        tips: 'h2',
        info: '.cart .status',
        box: '.step1-coosenum',
        tpl: 'tpl_item',
        cost: 2
    },
    build: function(ops, self) {
        var container = self.container = doc.getElement(ops.container);
        self.cost = ops.cost;
        self.tabs = new ns.Tabs(Object.merge({key: cfgs.key}, cfgs.tabs));
        self.tips = container.getElement(ops.tips);
        self.info = container.getElement(ops.info);
		self.box = container.getElement(ops.box).addClass(cfgs.key + '-step1');
        self.tpl = Template(ops.tpl);
        self.plays = {};
		self.editPlays = {};
        self.history = new History(cfgs.history).addEvent('got', self.updateHistory);
    },
    observe: function(self, action, actions) {
        self.tabs[action]('change', self.render);
		self.info.getNext()[action]('click:relay(input)', self.clear);
	},
    updateHistory: function (json) {
        var self = this;
        if (self.play) {
            self.play.updateHistory(json);
        }
    },
    render: function (newItem) {
        var self = this,
            plays = self.plays,
            type = newItem.getValue(),
            play = self.play,
            newPlay = plays[type];
        if (!newPlay) {
            newPlay = ns.getPlay(type);
            if (newPlay) {
                newPlay = new newPlay(Object.merge({type: type, cost: self.cost}, cfgs.plays[type])).addEvent('change', self.update).inject(self.box);
				newPlay.addClass('play' + type);
            }
        }
        if (newPlay) {
            if (play) {
                play.hide();  
            }
            newPlay.show(self.tips);
            self.play = plays[type] = newPlay;
            if (self.history.data) {
               self.play.updateHistory(self.history.data); 
            }
            self.update();
        }
    },
    update: function (info, tpl) {
        var self = this,
            ops = self.options;
		info = info || {nums:0, count:0, counts: [0, 0, 0, 0, 0, 0]};
		self.info.set('html', Template(tpl || self.play.getTpl(), info));
        /*infos[0].set('text', info.nums);
        infos[1].set('text', info.count);
        infos[2].set('text', info.count * ops.cost);
		if ( info.blues != undefined ) self.info.getElement('.blue').set('text', info.blues);*/
        self.fireEvent('change', !info.count);
    },
    edit: function (el) {
        el = el.getParent('li');
        var self = this,
			plays = self.editPlays,
            type = el.get('data-type'),
            nums = el.get('data-nums'),
			play = plays[type],
            dialog = self.dialog;
		if (!play) { 
			play = ns.getPlay(type);
			if (play) {
				play = new play(Object.merge({type: type, cost: self.cost}, cfgs.plays[type]));
				play.addClass('play' + type);
			}
		}
		if (play) {
            if (!dialog) {
				dialog = self.dialog = new ns.EditPlay(Object.merge({info: self.options.info, infoContent:self.info.getParent().get('html'), cost: self.cost}, cfgs.edit));
                dialog.addEvent('save', self.modify);
            }
			plays[type] = play;
            dialog.fill(play, el);
			if (self.history.data) {
            	play.updateHistory(self.history.data); 
            }
        }
    },
    modify: function (play, el) {
        var self = this,
            html = play.get(0, self.tpl),
            newEl = new Element('div').set('html', html).getFirst();
        newEl.replaces(el);
        self.fireEvent('save');
    },
    clear: function (e) {
        e && e.preventDefault();
        var self = this;
        self.play.clear();
        self.info.getElements('strong,.blue').set('text', 0);
        self.fireEvent('change', true);
    },
    get: function (n) {
        var self = this;
        return self.play.get(n, self.tpl);
    }
});

ns.StepTwo = new Class({
    Extends: ns.Base,
    Binds: ['addList', 'doAction', 'change', 'onChange', 'update'],
    options: {
        container: '.add-list',
        add: '.add_btn',
        list: '.list ul',
        info: '.cart .fc-red',
        action: '.action',
        field: '.syncdata',
        disabledClass: 'disabled'
    },
    initialize: function (options, step1) {
        var self = this;
        self.step1 = step1;
        self.parent(options);
    },
    build: function(ops, self) {
        var container = self.container = doc.getElement(ops.container);
        self.add = container.getElement(ops.add);
        self.list = container.getElement(ops.list);
        self.action = container.getElement(ops.action);
        self.info = container.getElements(ops.info);
        self.field = doc.getElement(ops.field).set('value', '');
    },
    observe: function(self, action, actions) {
        self.list[action]('click', self.change);
        self.add[action]('click', self.addList);
        self.action[action]('click:relay(a)', self.doAction);
        self.step1[action]('save', self.update);
    },
    addList: function (e, n, force) {
        var self = this,
            list = self.list,
            cls = self.options.disabledClass,
            datas,
            html;
        if (!self.add.hasClass(cls) || force) {
            datas = self.step1.get(n);
            html = [list.get('html')];
            if (datas) {
                html.push(datas);
                list.set('html', html.join(''));
                if (!n) {
                   self.step1.clear(); 
                }
                list.highlight();
                self.update();
                self.add.addClass(cls);
            }            
        }
    },
    onChange: function (disable) {
        var self = this;
        self.add[disable ? 'addClass' : 'removeClass'](self.options.disabledClass);
    },
    change: function (e) {
        var self = this,
            el = doc.id(e.target),
            tag = el.get('tag');
        if (tag == 'a') {
            if (el.hasClass('del')) {
                el.getParent('li').dispose();
                self.update();
            }            
            if (el.hasClass('edit')) {
               self.step1.edit(el);
            }            
        }
    },
    update: function (self) {
        var self = this,
            info = self.info,
            list = self.list.getElements('li');
            total = list.length ? eval(list.get('data-count').join('+')) : 0,
            data = [],
            key = cfgs.key,
            field = self.field;
        info[0].set('text', total);
        info[1].set('text', total * self.step1.cost);
        if (list.length) {
            list.each(function (li) {
                data.push({lottery: key, type: li.get('data-type'), data: li.get('data-nums')});
            });
            field.set('value', JSON.encode(data));
        } else field.set('value', '');
    },
    doAction: function (e) {
        e && e.preventDefault();
        var self = this,
            el = e.target,
            act;
        if (el.tagName != 'A') {
            el = el.parentNode;
        }
        act = el.get('data-act');
        if (act == 'clear') {
            if (self.list.getElements('li').length) {
                App.Confirm({
                    content: '您要清空所选数据？',
                    doOk: function () {
                      self.list.empty();
                      self.info.set('text', 0);
                      return true;
                    }
                });
            }
        } else {
            self.addList(e, act | 0, true);
        }
    }
});

ns.StepThree = new Class({
    Extends: ns.Base,
    Binds: ['handle'],
    options: {
        container: '.buy-now',
        times: '.bs',
        agreement: '#lab-agree',
        handler: '.buy_btn'
    },
    initialize: function (options, step2) {
        var self = this;
        self.step2 = step2;
        self.parent(options);
    },
    build: function(ops, self) {
        var container = self.container = doc.getElement(ops.container);
        self.times = doc.getElement(ops.times);
        self.handler = container.getElement(ops.handler);
        
    },
    observe: function(self, action, actions) {
        self.handler[action]('click', self.handle);
    },
    handle: function (e) {
        e && e.preventDefault();
        var self = this,
            ops = self.options,
            times = self.times.value.trim(),
            agreement = self.container.getElement(ops.agreement),
            msg,
            hl;
        if (!times) {
            msg = '请输入投注倍数';
        } else {
            if (/\D/.test(times)) {
                msg = '投注位数只允许为数字';
            }
            times = times | 0;
            if (times > 49 || times < 1) {
                msg = '最大投注倍数为49，最小投注位数为1';
            }
        }
        hl = !!msg;
        if (!msg && agreement && !agreement.checked) {
            msg =  '请阅读并同意《 委托投注规则 》';
        }
        if (msg) {
            App.Alert({
                content: msg,
                doOk: function () {
                    if (hl) {
                        self.times.highlight();
                    }
                }
            });
        }
    }
});

ns.Lottery = new Class({
    Extends: ns.Base,
    Binds: [],
    options: {
        container: '.main',
        wait: true
    },
    build: function(ops, self) {
        var container = self.container = doc.id(ops.container) || doc.getElement(ops.container);
        self.step1 = new ns.StepOne(cfgs.step1);
        self.step2 = new ns.StepTwo(cfgs.step2, self.step1);
        self.step3 = new ns.StepThree(cfgs.step3, self.step2);
    },
    observe: function(self, action, actions) {
        self.step1[action]('change', self.step2.onChange);
    }
});

})(using('HB'), this, document, this.configs || {});
